package collector

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	"go-agent/pkg/logger"
)

// NginxMetrics Nginx指标数据结构
type NginxMetrics struct {
	// 连接相关
	ActiveConnections int64     `json:"active_connections"`
	ServerAccepts     int64     `json:"server_accepts"`
	ServerHandled     int64     `json:"server_handled"`
	ServerRequests    int64     `json:"server_requests"`

	// 性能相关
	ResponseTime      float64   `json:"response_time"`     // 毫秒
	ResponseSizeLast  int64     `json:"response_size_last"` // 字节
	ResponseSlow      float64   `json:"response_slow"`      // 慢响应时间

	// 状态统计
	Reading          int64     `json:"reading"`
	Writing          int64     `json:"writing"`
	Waiting          int64     `json:"waiting"`

	// 采集时间戳
	Timestamp        time.Time `json:"timestamp"`
}

// NginxConfig Nginx采集器配置
type NginxConfig struct {
	Enabled         bool   `mapstructure:"enabled"`
	StatusURL       string `mapstructure:"status_url"`        // Nginx状态页面URL
	Timeout         int    `mapstructure:"timeout"`           // 请求超时时间（秒）
	SlowThreshold   int    `mapstructure:"slow_threshold"`    // 慢响应阈值（毫秒）

	// HTTP客户端配置
	UserAgent       string `mapstructure:"user_agent"`
	Headers         map[string]string `mapstructure:"headers"`
}

// NginxCollector Nginx采集器
type NginxCollector struct {
	config     NginxConfig
	httpClient *http.Client

	// 正则表达式编译缓存
	statusRegex *regexp.Regexp

	// 历史数据，用于计算差值
	lastMetrics *NginxMetrics
}

// NewNginxCollector 创建Nginx采集器
func NewNginxCollector(config NginxConfig) *NginxCollector {
	// 设置默认值
	if config.StatusURL == "" {
		config.StatusURL = "http://127.0.0.1/nginx_status"
	}
	if config.Timeout == 0 {
		config.Timeout = 10
	}
	if config.SlowThreshold == 0 {
		config.SlowThreshold = 500 // 默认500ms
	}
	if config.UserAgent == "" {
		config.UserAgent = "go-agent-nginx-collector/1.0"
	}

	httpClient := &http.Client{
		Timeout: time.Duration(config.Timeout) * time.Second,
	}

	// 编译用于解析nginx状态的正则表达式
	statusRegex := regexp.MustCompile(`Active connections:\s*(\d+)\s*\n.*\n\s*(\d+)\s+(\d+)\s+(\d+)\s*\n.*Reading:\s*(\d+)\s*Writing:\s*(\d+)\s*Waiting:\s*(\d+)`)

	return &NginxCollector{
		config:      config,
		httpClient:  httpClient,
		statusRegex: statusRegex,
	}
}

// Collect 采集Nginx指标
func (c *NginxCollector) Collect(ctx context.Context) (*NginxMetrics, error) {
	if !c.config.Enabled {
		return nil, fmt.Errorf("Nginx采集器未启用")
	}

	start := time.Now()

	// 获取Nginx状态数据
	statusData, err := c.fetchNginxStatus(ctx)
	if err != nil {
		logger.Errorf("获取Nginx状态失败: %v", err)
		return nil, err
	}

	// 解析状态数据
	metrics, err := c.parseNginxStatus(statusData)
	if err != nil {
		logger.Errorf("解析Nginx状态失败: %v", err)
		return nil, err
	}

	// 计算响应时间
	responseTime := float64(time.Since(start).Nanoseconds()) / 1e6 // 转换为毫秒
	metrics.ResponseTime = responseTime

	// 检查是否为慢响应
	if responseTime > float64(c.config.SlowThreshold) {
		metrics.ResponseSlow = responseTime
	}

	// 设置时间戳
	metrics.Timestamp = time.Now()

	// 保存当前指标用于下次计算差值
	c.lastMetrics = metrics

	logger.Debugf("Nginx指标采集完成: 活动连接=%d, 响应时间=%.2fms",
		metrics.ActiveConnections, metrics.ResponseTime)

	return metrics, nil
}

// fetchNginxStatus 获取Nginx状态页面内容
func (c *NginxCollector) fetchNginxStatus(ctx context.Context) (string, error) {
	req, err := http.NewRequestWithContext(ctx, "GET", c.config.StatusURL, nil)
	if err != nil {
		return "", fmt.Errorf("创建HTTP请求失败: %v", err)
	}

	// 设置User-Agent
	req.Header.Set("User-Agent", c.config.UserAgent)

	// 设置自定义头部
	for key, value := range c.config.Headers {
		req.Header.Set(key, value)
	}

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("HTTP请求失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("HTTP状态码错误: %d", resp.StatusCode)
	}

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应内容失败: %v", err)
	}

	return string(body), nil
}

// parseNginxStatus 解析Nginx状态页面内容
func (c *NginxCollector) parseNginxStatus(statusData string) (*NginxMetrics, error) {
	metrics := &NginxMetrics{}

	// 使用正则表达式解析标准格式的nginx状态
	matches := c.statusRegex.FindStringSubmatch(statusData)
	if len(matches) >= 8 {
		// 解析匹配的数字
		if val, err := strconv.ParseInt(matches[1], 10, 64); err == nil {
			metrics.ActiveConnections = val
		}
		if val, err := strconv.ParseInt(matches[2], 10, 64); err == nil {
			metrics.ServerAccepts = val
		}
		if val, err := strconv.ParseInt(matches[3], 10, 64); err == nil {
			metrics.ServerHandled = val
		}
		if val, err := strconv.ParseInt(matches[4], 10, 64); err == nil {
			metrics.ServerRequests = val
		}
		if val, err := strconv.ParseInt(matches[5], 10, 64); err == nil {
			metrics.Reading = val
		}
		if val, err := strconv.ParseInt(matches[6], 10, 64); err == nil {
			metrics.Writing = val
		}
		if val, err := strconv.ParseInt(matches[7], 10, 64); err == nil {
			metrics.Waiting = val
		}

		return metrics, nil
	}

	// 如果正则匹配失败，尝试逐行解析
	return c.parseNginxStatusByLines(statusData)
}

// parseNginxStatusByLines 逐行解析Nginx状态
func (c *NginxCollector) parseNginxStatusByLines(statusData string) (*NginxMetrics, error) {
	metrics := &NginxMetrics{}
	scanner := bufio.NewScanner(strings.NewReader(statusData))

	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		if strings.HasPrefix(line, "Active connections:") {
			// Active connections: 291
			parts := strings.Fields(line)
			if len(parts) >= 3 {
				if val, err := strconv.ParseInt(parts[2], 10, 64); err == nil {
					metrics.ActiveConnections = val
				}
			}
		} else if strings.Contains(line, "server accepts handled requests") {
			// 下一行应该是数字: " 16630948 16630948 31070465"
			if scanner.Scan() {
				numberLine := strings.TrimSpace(scanner.Text())
				parts := strings.Fields(numberLine)
				if len(parts) >= 3 {
					if val, err := strconv.ParseInt(parts[0], 10, 64); err == nil {
						metrics.ServerAccepts = val
					}
					if val, err := strconv.ParseInt(parts[1], 10, 64); err == nil {
						metrics.ServerHandled = val
					}
					if val, err := strconv.ParseInt(parts[2], 10, 64); err == nil {
						metrics.ServerRequests = val
					}
				}
			}
		} else if strings.Contains(line, "Reading:") && strings.Contains(line, "Writing:") && strings.Contains(line, "Waiting:") {
			// Reading: 6 Writing: 179 Waiting: 106
			readingRegex := regexp.MustCompile(`Reading:\s*(\d+)`)
			writingRegex := regexp.MustCompile(`Writing:\s*(\d+)`)
			waitingRegex := regexp.MustCompile(`Waiting:\s*(\d+)`)

			if match := readingRegex.FindStringSubmatch(line); len(match) > 1 {
				if val, err := strconv.ParseInt(match[1], 10, 64); err == nil {
					metrics.Reading = val
				}
			}
			if match := writingRegex.FindStringSubmatch(line); len(match) > 1 {
				if val, err := strconv.ParseInt(match[1], 10, 64); err == nil {
					metrics.Writing = val
				}
			}
			if match := waitingRegex.FindStringSubmatch(line); len(match) > 1 {
				if val, err := strconv.ParseInt(match[1], 10, 64); err == nil {
					metrics.Waiting = val
				}
			}
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("扫描状态数据失败: %v", err)
	}

	return metrics, nil
}

// GetMetricValue 根据字段路径获取指标值
func (c *NginxCollector) GetMetricValue(metrics *NginxMetrics, fieldPath string) interface{} {
	if metrics == nil {
		return nil
	}

	switch fieldPath {
	case "Connections.Active":
		return metrics.ActiveConnections
	case "Request.Time":
		return metrics.ResponseTime
	case "Response.Time":
		return metrics.ResponseTime
	case "Response.LastSize":
		return metrics.ResponseSizeLast
	case "Response.Slow":
		return metrics.ResponseSlow
	case "Server.Accepts":
		return metrics.ServerAccepts
	case "Server.Handled":
		return metrics.ServerHandled
	case "Server.Requests":
		return metrics.ServerRequests
	case "Connection.Reading":
		return metrics.Reading
	case "Connection.Writing":
		return metrics.Writing
	case "Connection.Waiting":
		return metrics.Waiting
	default:
		logger.Warnf("未知的Nginx指标字段路径: %s", fieldPath)
		return nil
	}
}

// Close 关闭采集器
func (c *NginxCollector) Close() error {
	// Nginx采集器没有需要关闭的资源
	return nil
}